package com.zzk.im.hx.service.impl;

import com.zzk.im.tool.Constant;
import com.zzk.im.tool.JsonTool;
import com.zzk.im.tool.TokenTool;
import com.zzk.im.hx.model.HXResponseObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import com.zzk.im.hx.service.HXHttpService;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.Map;
import java.util.Map.Entry;

import static com.zzk.im.tool.TokenTool.getToken;


@Service
public class HXHttpServiceImpl implements HXHttpService {

    Logger logger = Logger.getLogger(HXHttpServiceImpl.class);

    public HXResponseObject request(String url, int method, Object param, Boolean needToken,
                                    String[][] field) throws Exception {
        return request(url, method, param, needToken, field, 0);
    }

    private HXResponseObject request(String url, int method, Object param, Boolean needToken,
                                     String[][] field, int retryCount) throws Exception {
        CloseableHttpClient client = this.getClient();
        CloseableHttpResponse response = null;

        try {
            switch (method) {
                case Constant.HTTP_METHOD_GET:
                    HttpGet get = new HttpGet(url);
                    if (needToken) {
                        get.addHeader("Authorization", "Bearer " + TokenTool.getToken(false));
                    }
                    get.addHeader("Content-Type", "application/json");
                    response = client.execute(get);
                    break;
                case Constant.HTTP_METHOD_POST:
                    HttpPost post = new HttpPost(url);
                    if (needToken) {
                        post.addHeader("Authorization", "Bearer " + TokenTool.getToken(false));
                    }
                    if (param != null) {
                        post.setEntity(new StringEntity(JsonTool.write(param),
                                "UTF-8"));
                    }
                    post.addHeader("Content-Type", "application/json");
                    response = client.execute(post);
                    break;
                case Constant.HTTP_METHOD_PUT:
                    HttpPut put = new HttpPut(url);
                    if (needToken) {
                        put.addHeader("Authorization", "Bearer " + TokenTool.getToken(false));
                    }
                    if (param != null) {
                        put.setEntity(new StringEntity(JsonTool.write(param),
                                "UTF-8"));
                    }
                    put.addHeader("Content-Type", "application/json");
                    response = client.execute(put);
                    break;
                case Constant.HTTP_METHOD_DELETE:
                    HttpDelete delete = new HttpDelete(url);
                    if (needToken) {
                        delete.addHeader("Authorization", "Bearer " + TokenTool.getToken(false));
                    }
                    delete.addHeader("Content-Type", "application/json");
                    response = client.execute(delete);
                    break;
                default:
                    throw new Exception("非法请求方式");
            }


            int code = response.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String json = EntityUtils.toString(entity, "UTF-8");
                    if (field != null && field.length > 0) {
                        for (String[] temp : field) {
                            json = json.replace(temp[0], temp[1]);
                        }
                    }

                    HXResponseObject responseObject = (HXResponseObject) JsonTool.read(json, HXResponseObject.class);
                    responseObject.setStatusCode(code);
                    return responseObject;
                }
            } else if (code == HttpStatus.SC_UNAUTHORIZED) {
                if (retryCount >= 2) {
                    throw new RuntimeException("尝试获取token失败2次,不再重新获取");
                }
                logger.info("======================token已经过期,正在重新获取========================");
                getToken(true);
                return request(url, method, param, needToken, field, retryCount++);
            } else {
                return new HXResponseObject(code);
            }
        } catch (Exception e) {
            logger.error(e);
            throw e;
        } finally {
            client.close();
        }
        return null;
    }

    public HXResponseObject upload(String url, File file, Boolean needToken,
                                   String[][] equal) throws Exception {
        return upload(url, file, needToken, equal, 0);
    }


    private HXResponseObject upload(String url, File file, Boolean needToken,
                                    String[][] equal, int retryCount) throws Exception {
        CloseableHttpClient client = this.getClient();
        try {
            HttpPost post = new HttpPost();
            post.setURI(new URI(url));
            if (needToken) {
                post.addHeader("Authorization", "Bearer " + TokenTool.getToken(false));
            }
            post.addHeader("restrict-access", "true");
            ContentBody body = new FileBody(file);
            MultipartEntity part = new MultipartEntity();
            part.addPart("file", body);
            post.setEntity(part);
            HttpResponse response = client.execute(post);
            int code = response.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String json = EntityUtils.toString(entity, "UTF-8");
                    if (equal != null && equal.length > 0) {
                        for (String[] temp : equal) {
                            json = json.replace(temp[0], temp[1]);
                        }
                    }
                    HXResponseObject talkNode = (HXResponseObject) JsonTool.read(json, HXResponseObject.class);
                    talkNode.setStatusCode(code);
                    return talkNode;
                }
            } else if (code == HttpStatus.SC_UNAUTHORIZED) {
                if (retryCount >= 2) {
                    throw new RuntimeException("尝试获取token失败2次,不再重新获取");
                }
                logger.info("======================token已经过期,正在重新获取========================");
                getToken(true);
                return upload(url, file, needToken, equal, retryCount++);
            } else {
                return new HXResponseObject(code);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            client.close();
        }
        return null;
    }

    public HXResponseObject downLoad(String url, File file, Boolean needToken,
                                     Map<String, String> header) throws Exception {
        return downLoad(url, file, needToken, header, 0);
    }

    private HXResponseObject downLoad(String url, File file, Boolean needToken,
                                      Map<String, String> header, int retryCount) throws Exception {
        CloseableHttpClient client = this.getClient();
        try {
            HttpGet get = new HttpGet();
            get.setURI(new URI(url));
            if (needToken) {
                get.addHeader("Authorization", "Bearer " + TokenTool.getToken(false));
            }
            for (Entry<String, String> en : header.entrySet()) {
                get.addHeader(en.getKey(), en.getValue());
            }
            HttpResponse response = client.execute(get);
            int code = response.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    InputStream in = entity.getContent();
                    FileOutputStream fos = new FileOutputStream(file);
                    byte[] data = new byte[10 * 1024];
                    int len = 0;
                    while ((len = in.read(data)) != -1) {
                        fos.write(data, 0, len);
                    }
                    fos.flush();
                    fos.close();
                    in.close();
                }
                return new HXResponseObject(HttpStatus.SC_OK);
            } else if (code == HttpStatus.SC_UNAUTHORIZED) {
                if (retryCount >= 2) {
                    throw new RuntimeException("尝试获取token失败2次,不再重新获取");
                }
                logger.info("======================token已经过期,正在重新获取========================");
                getToken(true);
                return downLoad(url, file, needToken, header ,retryCount++);
            } else {
                return new HXResponseObject(code);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            client.close();
        }
    }

    private CloseableHttpClient getClient() {
        return HttpClients.createDefault();
    }
}